package com.ruoyi.business.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.business.app.bo.AppMerchantQueryBo;
import com.ruoyi.business.app.bo.HcxMerchantJoinBo;
import com.ruoyi.business.app.vo.AppMerchantDetailVo;
import com.ruoyi.business.app.vo.AppMerchantPhotoVo;
import com.ruoyi.business.app.vo.AppMerchantProductVo;
import com.ruoyi.business.app.vo.AppMerchantVo;
import com.ruoyi.business.bo.HcxMerchantAddBo;
import com.ruoyi.business.bo.HcxMerchantEditBo;
import com.ruoyi.business.bo.HcxMerchantQueryBo;
import com.ruoyi.business.domain.*;
import com.ruoyi.business.mapper.HcxMerchantMapper;
import com.ruoyi.business.mapper.HcxMerchantTypeMapper;
import com.ruoyi.business.service.*;
import com.ruoyi.business.vo.HcxMerchantVo;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.HcxMerchantType;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.ruoyi.common.core.page.PagePlus;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.AssertUtils;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.mapper.SysUserRoleMapper;
import com.ruoyi.system.service.ISysUserService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 商家Service业务层处理
 *
 * @author wsdz
 * @date 2022-08-17
 */
@Service
@AllArgsConstructor
public class HcxMerchantServiceImpl extends ServicePlusImpl<HcxMerchantMapper, HcxMerchant> implements IHcxMerchantService {

    private final IHcxMerchantPhotoService iHcxMerchantPhotoService;

    private final IHcxAppUserService appUserService;

    private final ISysUserService userService;

    private final SysUserRoleMapper userRoleMapper;

    private final IHcxMerchantProductService merchantProductService;

    private final IHcxMerchantOrderService iHcxMerchantOrderService;

    private final HcxMerchantTypeMapper merchantTypeMapper;


    @Override

    public HcxMerchantVo queryById(Long id) {
        HcxMerchantVo hcxMerchantVo = getVoById(id, HcxMerchantVo.class);
        // 查询门面照
        List<HcxMerchantPhoto> list = iHcxMerchantPhotoService.list(new LambdaQueryWrapper<HcxMerchantPhoto>().eq(HcxMerchantPhoto::getMerchantId, hcxMerchantVo.getId()));
        List<String> photos = list.stream().map(HcxMerchantPhoto::getPicUrl).collect(Collectors.toList());
        hcxMerchantVo.setPhotos(photos);
        return hcxMerchantVo;
    }

    @Override
    public TableDataInfo<HcxMerchantVo> queryPageList(HcxMerchantQueryBo bo) {
        PagePlus<HcxMerchant, HcxMerchantVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo), HcxMerchantVo.class);
        return PageUtils.buildDataInfo(result);
    }

    @Override
    public List<HcxMerchantVo> queryList(HcxMerchantQueryBo bo) {
        return listVo(buildQueryWrapper(bo), HcxMerchantVo.class);
    }

    private LambdaQueryWrapper<HcxMerchant> buildQueryWrapper(HcxMerchantQueryBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<HcxMerchant> lqw = Wrappers.lambdaQuery();
        lqw.like(StrUtil.isNotBlank(bo.getPersonName()), HcxMerchant::getPersonName, bo.getPersonName());
        lqw.eq(StrUtil.isNotBlank(bo.getPersonTel()), HcxMerchant::getPersonTel, bo.getPersonTel());
        lqw.like(StrUtil.isNotBlank(bo.getMerchantName()), HcxMerchant::getMerchantName, bo.getMerchantName());
        lqw.eq(bo.getTypeId() != null, HcxMerchant::getTypeId, bo.getTypeId());
        lqw.like(StrUtil.isNotBlank(bo.getTypeName()), HcxMerchant::getTypeName, bo.getTypeName());
        lqw.eq(StrUtil.isNotBlank(bo.getStartTime()), HcxMerchant::getStartTime, bo.getStartTime());
        lqw.eq(StrUtil.isNotBlank(bo.getEndTime()), HcxMerchant::getEndTime, bo.getEndTime());
        lqw.eq(bo.getLongitude() != null, HcxMerchant::getLongitude, bo.getLongitude());
        lqw.eq(bo.getLatitude() != null, HcxMerchant::getLatitude, bo.getLatitude());
        lqw.eq(StrUtil.isNotBlank(bo.getAddress()), HcxMerchant::getAddress, bo.getAddress());
        lqw.like(StrUtil.isNotBlank(bo.getProvinceName()), HcxMerchant::getProvinceName, bo.getProvinceName());
        lqw.eq(StrUtil.isNotBlank(bo.getProvinceCode()), HcxMerchant::getProvinceCode, bo.getProvinceCode());
        lqw.like(StrUtil.isNotBlank(bo.getCityName()), HcxMerchant::getCityName, bo.getCityName());
        lqw.eq(StrUtil.isNotBlank(bo.getCityCode()), HcxMerchant::getCityCode, bo.getCityCode());
        lqw.like(StrUtil.isNotBlank(bo.getDistrictsName()), HcxMerchant::getDistrictsName, bo.getDistrictsName());
        lqw.eq(StrUtil.isNotBlank(bo.getDistrictsCode()), HcxMerchant::getDistrictsCode, bo.getDistrictsCode());
        lqw.eq(StrUtil.isNotBlank(bo.getIntroduce()), HcxMerchant::getIntroduce, bo.getIntroduce());
        lqw.eq(StrUtil.isNotBlank(bo.getBusinessUrl()), HcxMerchant::getBusinessUrl, bo.getBusinessUrl());
        lqw.eq(StrUtil.isNotBlank(bo.getOtherUrl()), HcxMerchant::getOtherUrl, bo.getOtherUrl());
        lqw.eq(StrUtil.isNotBlank(bo.getUserSig()), HcxMerchant::getUserSig, bo.getUserSig());
        lqw.eq(StrUtil.isNotBlank(bo.getImId()), HcxMerchant::getImId, bo.getImId());
        lqw.eq(StrUtil.isNotBlank(bo.getDelFlag()), HcxMerchant::getDelFlag, bo.getDelFlag());
        return lqw;
    }

    @Override
    @Transactional
    public Boolean insertByAddBo(HcxMerchantAddBo bo) {
        HcxMerchant add = BeanUtil.toBean(bo, HcxMerchant.class);
        validEntityBeforeSave(add);
        bo.setStatus(Constants.ZERO);
        boolean save = save(add);
        // 保存新的门面照
        String[] photos = bo.getPhotos();
        if (ObjectUtil.isNotEmpty(photos)) {
            List<HcxMerchantPhoto> list = new ArrayList<>();
            for (int i = 0; i < photos.length; i++) {
                HcxMerchantPhoto hcxMerchantPhoto = new HcxMerchantPhoto();
                hcxMerchantPhoto.setPicUrl(photos[i]);
                hcxMerchantPhoto.setMerchantId(add.getId());
                hcxMerchantPhoto.setMerchantName(bo.getMerchantName());
                hcxMerchantPhoto.setOrderSort(i + 1);
                list.add(hcxMerchantPhoto);
            }
            iHcxMerchantPhotoService.saveBatch(list);
        }


        return save;
    }

    @Override
    @Transactional
    public Boolean updateByEditBo(HcxMerchantEditBo bo) {
        HcxMerchant update = BeanUtil.toBean(bo, HcxMerchant.class);
        validEntityBeforeSave(update);
        // 先删除之前旧的门面照
        iHcxMerchantPhotoService.remove(new LambdaQueryWrapper<HcxMerchantPhoto>().eq(HcxMerchantPhoto::getMerchantId, bo.getId()));

        // 保存新的门面照
        String[] photos = bo.getPhotos();
        if (ObjectUtil.isNotEmpty(photos)) {
            List<HcxMerchantPhoto> list = new ArrayList<>();
            for (int i = 0; i < photos.length; i++) {
                HcxMerchantPhoto hcxMerchantPhoto = new HcxMerchantPhoto();
                hcxMerchantPhoto.setPicUrl(photos[i]);
                hcxMerchantPhoto.setMerchantId(bo.getId());
                hcxMerchantPhoto.setMerchantName(bo.getMerchantName());
                hcxMerchantPhoto.setOrderSort(i + 1);
                list.add(hcxMerchantPhoto);
            }
            iHcxMerchantPhotoService.saveBatch(list);
        }
        return updateById(update);
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(HcxMerchant entity) {
        // 判断商家名称是否存在
        HcxMerchant hcxMerchant = getOne(new LambdaQueryWrapper<HcxMerchant>()
                .eq(HcxMerchant::getMerchantName, entity.getMerchantName())
                .last("limit 1")
        );
        // 如果是新增操作
        if (ObjectUtil.isEmpty(entity.getId())) {
            AssertUtils.isTrue(ObjectUtil.isEmpty(hcxMerchant), "新增商家名称" + entity.getMerchantName() + ",失败，商家名称已存在");
        } else {
            if (ObjectUtil.isNotEmpty(hcxMerchant) && entity.getId().longValue() != hcxMerchant.getId().longValue()) {
                throw new CustomException("修改商家名称" + entity.getMerchantName() + ",失败，商家名称已存在");
            }
        }
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return removeByIds(ids);
    }

    @Override
    public String importHcxMerchant(List<HcxMerchantVo> hcxMerchantList) {
        AssertUtils.isTrue(CollectionUtils.isNotEmpty(hcxMerchantList), "导入数据不能为空");
        int successNum = 0;
        for (HcxMerchantVo hcxMerchant : hcxMerchantList) {
            HcxMerchant add = BeanUtil.toBean(hcxMerchant, HcxMerchant.class);
            save(add);
            successNum++;
        }
        String msg = String.format("导入完成，共计 %d 条数据，成功 %d 条！", hcxMerchantList.size(), successNum);
        if (successNum != hcxMerchantList.size()) {
            msg = msg + String.format("失败 %d 条！", hcxMerchantList.size() - successNum);
        }
        return msg;
    }


    /**
     * 直接程序计算两个坐标之间的距离
     */
    public static Double getDis(Double lat1, Double lon1, Double lat2, Double lon2) {
        Double radLat1 = (lat1 * Math.PI) / 180;
        Double radLat2 = (lat2 * Math.PI) / 180;
        Double a = radLat1 - radLat2;
        Double b = (lon1 * Math.PI) / 180 - (lon2 * Math.PI) / 180;
        Double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(
                Math.sin(b / 2), 2)));
        s = s * 6378137.0;
        return s;
    }

    @Override
    public TableDataInfo<AppMerchantVo> queryAppPageList(AppMerchantQueryBo bo) {

        Page<AppMerchantVo> result;
        if (StringUtils.isBlank(bo.getLongitude()) || StringUtils.isBlank(bo.getLatitude())) {
            result = getBaseMapper().selectPageMerchantListNoDingwei(PageUtils.buildPage(), bo);
            List<AppMerchantVo> records = result.getRecords();
            for (AppMerchantVo record : records) {
                // 取第一张门面照
                List<HcxMerchantPhoto> list = iHcxMerchantPhotoService.list(new LambdaQueryWrapper<HcxMerchantPhoto>().eq(HcxMerchantPhoto::getMerchantId, record.getId()).orderByAsc(HcxMerchantPhoto::getOrderSort));
                if (CollectionUtil.isNotEmpty(list)) {
                    record.setPicUrl(list.get(0).getPicUrl());
                }
            }
            return PageUtils.buildDataInfo(result);
        }
        result = getBaseMapper().selectPageMerchantList(PageUtils.buildPage(), bo);
        List<AppMerchantVo> records = result.getRecords();
        for (AppMerchantVo record : records) {
            // 单位米
            double distance = Double.valueOf(record.getDistance());
            String juli;
            // 如果距离大于1KM则转换为km 否则用米显示
            if (distance > 1000) {
                // 转换为千米并保留两位小数
                String distanceQm = new BigDecimal(distance).divide(new BigDecimal(1000)).setScale(2, BigDecimal.ROUND_HALF_UP).toString() + "km";
                juli = distanceQm;
            } else {
                if (distance == 0) {
                    juli = "0m";
                } else {
                    DecimalFormat format = new DecimalFormat("#.00");
                    juli = format.format(distance) + "m";
                }
            }
            record.setDistance(juli);

            // 取第一张门面照
            List<HcxMerchantPhoto> list = iHcxMerchantPhotoService.list(new LambdaQueryWrapper<HcxMerchantPhoto>().eq(HcxMerchantPhoto::getMerchantId, record.getId()).orderByAsc(HcxMerchantPhoto::getOrderSort));
            if (CollectionUtil.isNotEmpty(list)) {
                record.setPicUrl(list.get(0).getPicUrl());
            }
        }
        return PageUtils.buildDataInfo(result);
    }

    @Override
    public AppMerchantDetailVo queryAppById(Long id) {
        AppMerchantDetailVo appMerchantDetailVo = getVoById(id, AppMerchantDetailVo.class);
        // 查询门面照片
        List<AppMerchantPhotoVo> photoList = iHcxMerchantPhotoService.listVo(new LambdaQueryWrapper<HcxMerchantPhoto>()
                        .eq(HcxMerchantPhoto::getMerchantId, id)
                        .orderByAsc(HcxMerchantPhoto::getOrderSort)
                , AppMerchantPhotoVo.class);
        appMerchantDetailVo.setPhotos(photoList);
        // 查询商家产品信息
        List<AppMerchantProductVo> productList = merchantProductService.listVo(new LambdaQueryWrapper<HcxMerchantProduct>().eq(HcxMerchantProduct::getMerchantId, id), AppMerchantProductVo.class);
        appMerchantDetailVo.setProducts(productList);
        // 查询商家订单数量
        int count = iHcxMerchantOrderService.count(new LambdaQueryWrapper<HcxMerchantOrder>()
                .eq(HcxMerchantOrder::getMerchantId, id)
                .gt(HcxMerchantOrder::getStatus, 0)
                .lt(HcxMerchantOrder::getStatus, 4)
        );
        appMerchantDetailVo.setSaleNum(count);
        return appMerchantDetailVo;
    }

    @Override
    @Transactional
    public Boolean join(HcxMerchantJoinBo bo) {

        Boolean result;
        HcxMerchant hcxMerchant;
        // 如果以前没有提交过
        if (ObjectUtil.isEmpty(bo.getId())) {
            hcxMerchant = BeanUtil.toBean(bo, HcxMerchant.class);
            hcxMerchant.setStatus(Constants.ZERO);
            hcxMerchant.setUserId(SecurityUtils.getUserId());
            result = save(hcxMerchant);
        } else {
            // 状态是未审核通过的
            hcxMerchant = getOne(new LambdaQueryWrapper<HcxMerchant>().eq(HcxMerchant::getId, bo.getId()));
            BeanUtil.copyProperties(bo, hcxMerchant);
            // 状态修改为0待审核
            hcxMerchant.setStatus(Constants.ZERO);

            // 删除之前的门面照片
            if (CollectionUtil.isNotEmpty(bo.getPhotos())) {
                List<HcxMerchantPhoto> list = iHcxMerchantPhotoService.list(new LambdaQueryWrapper<HcxMerchantPhoto>().eq(HcxMerchantPhoto::getMerchantId, bo.getId()));
                List<Long> collect = list.stream().map(HcxMerchantPhoto::getId).collect(Collectors.toList());
                iHcxMerchantPhotoService.deleteWithValidByIds(collect, false);
            }
            // 更新状态
            result = updateById(hcxMerchant);

        }

        List<String> photos = bo.getPhotos();
        if (CollectionUtil.isNotEmpty(photos)) {
            List<HcxMerchantPhoto> list = new ArrayList<>();

            for (int i = 0; i < photos.size(); i++) {
                HcxMerchantPhoto hcxMerchantPhoto = new HcxMerchantPhoto();
                hcxMerchantPhoto.setPicUrl(photos.get(i));
                hcxMerchantPhoto.setMerchantId(hcxMerchant.getId());
                hcxMerchantPhoto.setMerchantName(bo.getMerchantName());
                hcxMerchantPhoto.setOrderSort(i + 1);
                list.add(hcxMerchantPhoto);
            }

            result = iHcxMerchantPhotoService.saveBatch(list);
        }
        return result;
    }

    @Override
    @Transactional
    public Boolean audit(HcxMerchantEditBo bo) {
        HcxMerchant update = BeanUtil.toBean(bo, HcxMerchant.class);
        boolean result = updateById(update);
        // 审核通过后 生成账号 用来登录后台
        if (Constants.ONE.equals(bo.getStatus())) {
            HcxAppUser hcxAppUser = appUserService.getById(bo.getUserId());
            // 修改用戶merchant_flag为商家
            hcxAppUser.setMerchantFlag(Constants.ONE);
            result = appUserService.updateById(hcxAppUser);

            // 判断是不是之前创建过
            String s = userService.checkUserNameUnique(hcxAppUser.getUserName());

            // 如果没有创建过用户 (手机号唯一 这里手机号 和 username一样)
            if (UserConstants.UNIQUE.equals(userService.checkUserNameUnique(hcxAppUser.getUserName()))) {

                // 则创建sys_user系统用户 用来登录后台
                SysUser sysUser = new SysUser();
                sysUser.setRoleId(Constants.merchantRoleId);
                sysUser.setUserName(hcxAppUser.getUserName());
                sysUser.setNickName(hcxAppUser.getNickName());
                sysUser.setPhonenumber(hcxAppUser.getPhonenumber());
                sysUser.setSex(hcxAppUser.getSex());
                sysUser.setStatus(Constants.ZERO);
                sysUser.setPassword(hcxAppUser.getPassword());


                result = userService.save(sysUser);

                // 新增用户与角色管理
                SysUserRole ur = new SysUserRole();
                ur.setUserId(sysUser.getUserId());
                ur.setRoleId(sysUser.getRoleId());
                int insert = userRoleMapper.insert(ur);
                result = insert > 0;

            }
        }
        return result;
    }

    @Override
    public HcxMerchantVo queryDetail() {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        // 根据手机号查到用户信息(hcx_app_user和sys_user 通过手机号定位到唯一一条记录)
        HcxAppUser one = appUserService.getOne(new LambdaQueryWrapper<HcxAppUser>().eq(HcxAppUser::getPhonenumber, loginUser.getUsername()));
        HcxMerchantVo vo = new HcxMerchantVo();
        if (ObjectUtil.isNotEmpty(one)) {
            vo = getVoOne(new LambdaQueryWrapper<HcxMerchant>().eq(HcxMerchant::getUserId, one.getId()), HcxMerchantVo.class);
        }
        // 查询商家的门面照信息
        List<String> photos = iHcxMerchantPhotoService.list(new LambdaQueryWrapper<HcxMerchantPhoto>().eq(HcxMerchantPhoto::getMerchantId, vo.getId())).stream().map(HcxMerchantPhoto::getPicUrl).collect(Collectors.toList());
        vo.setPhotos(photos);
        return vo;
    }

    /**
     * @description: 修改商家信息
     * @author: kubilewang
     * @date: 2022/8/22 17:36
     * @param: [bo]
     * @Return: [bo]
     **/
    @Override
    public Boolean updateMerchantYingye(HcxMerchantEditBo bo) {
        HcxMerchant hcxMerchant = new HcxMerchant();
        hcxMerchant.setStartTime(bo.getStartTime());
        hcxMerchant.setEndTime(bo.getEndTime());
        hcxMerchant.setId(bo.getId());
        return updateById(hcxMerchant);
    }

    @Override
    public List<HcxMerchantType> classification() {
        HcxMerchantType merchantType = new HcxMerchantType();
        return merchantTypeMapper.selectMerchantTypeList(merchantType);
    }


}
